package top.lixunda.ecommerce.server.good.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import top.lixunda.common.utils.ObjectValidators;
import top.lixunda.ecommerce.server.business.BaseServiceImpl;
import top.lixunda.ecommerce.server.business.api.entity.cache.CacheStore;
import top.lixunda.ecommerce.server.good.api.entity.db.GoodGroupDO;
import top.lixunda.ecommerce.server.good.api.entity.dto.GoodGroupInsertDTO;
import top.lixunda.ecommerce.server.good.api.entity.dto.GoodGroupUpdateDTO;
import top.lixunda.ecommerce.server.good.api.entity.vo.GoodGroupTreeVO;
import top.lixunda.ecommerce.server.good.mapper.GoodGroupMapper;
import top.lixunda.ecommerce.server.good.service.IGoodGroupService;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 店铺商品分组表(树形结构) 服务实现类
 * </p>
 *
 * @author Xumda
 * @since 2019-12-18
 */
@Service
public class GoodGroupServiceImpl
        extends BaseServiceImpl<GoodGroupMapper, GoodGroupDO>
        implements IGoodGroupService {

    /**
     * 添加一个商品分组
     *
     * @param goodGroupInsertDTO 新添加的商品分组数据
     * @return 是否添加成功
     */
    @Override
    public boolean insertGoodGroup(GoodGroupInsertDTO goodGroupInsertDTO) {
        if (ObjectValidators.isEmpty(goodGroupInsertDTO)) {
            throw getAppException("参数不能为空");
        }
        CacheStore cacheStore = currentStoreCacheNotNull();
        boolean isRoot = !(goodGroupInsertDTO.getParentId() != null && goodGroupInsertDTO.getParentId() > 0);
        GoodGroupDO goodGroupDO = new GoodGroupDO();
        goodGroupDO.setCreateTime(LocalDateTime.now())
                .setCreateUserId(cacheStore.getId())
                .setCreateUserName(cacheStore.getName())
                .setIsLeaf(GoodGroupDO.LEAF_IS)
                .setIsRoot(isRoot ? GoodGroupDO.ROOT_IS : GoodGroupDO.ROOT_NOT)
                .setDescription(goodGroupInsertDTO.getDescription())
                .setName(goodGroupInsertDTO.getName())
                .setRemark(goodGroupInsertDTO.getRemark())
                .setParent(isRoot ? 0 : goodGroupInsertDTO.getParentId())
                .setStoreId(cacheStore.getId())
                .setStoreName(cacheStore.getName());
        return this.save(goodGroupDO);
    }

    /**
     * 更新一个商品分组
     *
     * @param goodGroupUpdateDTO 需要更新的商品分组数据
     * @return 是否更新成功
     */
    @Override
    public boolean updateGoodGroup(GoodGroupUpdateDTO goodGroupUpdateDTO) {
        if (ObjectValidators.isEmpty(goodGroupUpdateDTO)) {
            throw getAppException("参数不能为空");
        }
        CacheStore cacheStore = currentStoreCacheNotNull();
        GoodGroupDO goodGroupDO = this.getOne(new LambdaQueryWrapper<GoodGroupDO>()
                .eq(GoodGroupDO::getId, goodGroupUpdateDTO.getId())
                .eq(GoodGroupDO::getStoreId, cacheStore.getId()), false);
        if (ObjectValidators.isEmpty(goodGroupDO)) {
            throw getAppException("分组信息不存在");
        }
        goodGroupDO.setName(goodGroupUpdateDTO.getName())
                .setDescription(goodGroupUpdateDTO.getDescription())
                .setRemark(goodGroupUpdateDTO.getRemark());
        return this.updateById(goodGroupDO);
    }

    /**
     * 根据id删除商品分组，只删除该节点，其子节点全部放到父节点中去
     *
     * @param id 商品分组id
     * @return 是否删除成功
     */
    @Override
    public boolean removeGoodGroupById(Integer id) {
        if (ObjectValidators.isEmpty(id)) {
            throw getAppException("商品分组id不能为空");
        }
        CacheStore cacheStore = currentStoreCacheNotNull();
        GoodGroupDO goodGroupDO = this.getOne(new LambdaQueryWrapper<GoodGroupDO>()
                .eq(GoodGroupDO::getId, id)
                .eq(GoodGroupDO::getStoreId, cacheStore.getId()), false);
        if (ObjectValidators.isEmpty(goodGroupDO)) {
            throw getAppException("分组信息不存在");
        }
        // 把子节点放到父节点中去
        List<GoodGroupDO> list = this.list(new LambdaQueryWrapper<GoodGroupDO>()
                .eq(GoodGroupDO::getParent, id)
                .eq(GoodGroupDO::getStoreId, cacheStore.getId()));
        if (ObjectValidators.isNotEmpty(list)) {
            List<Integer> changeIds = list.stream()
                    .filter(Objects::nonNull)
                    .map(GoodGroupDO::getId)
                    .collect(Collectors.toList());
            if (ObjectValidators.isNotEmpty(changeIds)) {
                this.update(new LambdaUpdateWrapper<GoodGroupDO>()
                        .set(GoodGroupDO::getParent, goodGroupDO.getParent())
                        .set(GoodGroupDO::getIsRoot, goodGroupDO.getIsRoot())
                        .eq(GoodGroupDO::getStoreId, cacheStore.getId())
                        .in(GoodGroupDO::getId, changeIds));
            }
        }
        // 移除本身节点
        this.removeById(id);
        return true;
    }

    /**
     * 根据id删除商品分组，只删除该节点，其子节点全部放到父节点中去
     *
     * @param ids 商品分组id
     * @return 是否删除成功
     */
    @Override
    public boolean removeGoodGroupByIds(List<Integer> ids) {
        if (ObjectValidators.isEmpty(ids)) {
            throw getAppException("商品分组id不能为空");
        }
        for (Integer id : ids) {
            this.removeGoodGroupById(id);
        }
        return true;
    }

    /**
     * 根据id删除商品分组，删除包括子节点的所有节点
     *
     * @param id 商品分组id
     * @return 是否删除成功
     */
    @Override
    public boolean removeGoodGroupAllById(Integer id) {
        if (ObjectValidators.isEmpty(id)) {
            throw getAppException("商品分组id不能为空");
        }
        CacheStore cacheStore = currentStoreCacheNotNull();
        GoodGroupDO goodGroupDO = this.getOne(new LambdaQueryWrapper<GoodGroupDO>()
                .eq(GoodGroupDO::getId, id)
                .eq(GoodGroupDO::getStoreId, cacheStore.getId()), false);
        if (ObjectValidators.isEmpty(goodGroupDO)) {
            throw getAppException("分组信息不存在");
        }
        // 查询所有子节点
        List<GoodGroupDO> list = new ArrayList<>(128);
        list.add(goodGroupDO);
        List<Integer> selectIds = Collections.singletonList(id);
        List<GoodGroupDO> tempList;
        while (ObjectValidators.isNotEmpty(selectIds)) {
            tempList = this.list(new LambdaQueryWrapper<GoodGroupDO>()
                    .eq(GoodGroupDO::getStoreId, cacheStore.getId())
                    .in(GoodGroupDO::getParent, selectIds));
            list.addAll(tempList);
            selectIds = tempList.stream()
                    .map(GoodGroupDO::getId)
                    .collect(Collectors.toList());
        }
        selectIds = list.stream()
                .filter(Objects::nonNull)
                .map(GoodGroupDO::getId)
                .distinct()
                .collect(Collectors.toList());
        if (ObjectValidators.isNotEmpty(selectIds)) {
            this.removeByIds(selectIds);
        }
        return true;
    }

    /**
     * 根据id删除商品分组，删除包括子节点的所有节点
     *
     * @param ids 商品分组id
     * @return 是否删除成功
     */
    @Override
    public boolean removeGoodGroupAllByIds(List<Integer> ids) {
        if (ObjectValidators.isEmpty(ids)) {
            throw getAppException("商品分组id不能为空");
        }
        for (Integer id : ids) {
            this.removeGoodGroupAllById(id);
        }
        return true;
    }

    /**
     * 根据id获取分组数据信息
     *
     * @param id 分组id
     * @return 单条分组数据
     */
    @Override
    public GoodGroupDO queryById(Integer id) {
        if (ObjectValidators.isEmpty(id) || id <= 0) {
            throw getAppException("参数id不能为空获取小于等于零");
        }
        CacheStore cacheStore = currentStoreCacheNotNull();
        return this.getOne(new LambdaQueryWrapper<GoodGroupDO>()
                .eq(GoodGroupDO::getId, id)
                .eq(GoodGroupDO::getStoreId, cacheStore.getId()), false);
    }

    /**
     * 查询整个分组树
     *
     * @return 分组树
     */
    @Override
    public GoodGroupTreeVO queryTree() {
        CacheStore cacheStore = currentStoreCacheNotNull();
        List<GoodGroupDO> list = this.list(new LambdaQueryWrapper<GoodGroupDO>()
                .eq(GoodGroupDO::getStoreId, cacheStore.getId()));
        return GoodGroupTreeVO.fromGoodGroupDoList(list);
    }

    /**
     * 根据父节点id获取子类节点列表
     *
     * @param id 父节点id
     * @return 子节点列表
     */
    @Override
    public List<GoodGroupDO> queryChildrenByParentId(Integer id) {
        if (ObjectValidators.isEmpty(id) || id <= 0) {
            throw getAppException("参数id不能为空获取小于等于零");
        }
        CacheStore cacheStore = currentStoreCacheNotNull();
        return this.list(new LambdaQueryWrapper<GoodGroupDO>()
                .eq(GoodGroupDO::getParent, id)
                .eq(GoodGroupDO::getStoreId, cacheStore.getId()));
    }

    /**
     * 查询首层节点
     *
     * @return 首层节点
     */
    @Override
    public List<GoodGroupDO> queryRoots() {
        CacheStore cacheStore = currentStoreCacheNotNull();
        return this.list(new LambdaQueryWrapper<GoodGroupDO>()
                .eq(GoodGroupDO::getIsRoot, GoodGroupDO.ROOT_IS)
                .eq(GoodGroupDO::getStoreId, cacheStore.getId()));
    }

}
